<?php
// 应用公共文件

use app\common\service\AuthService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Cache;
use think\exception\HttpResponseException;

if (!function_exists('__url')) {

    /**
     * 构建URL地址
     * @param string $url
     * @param array $vars
     * @param bool $suffix
     * @param bool $domain
     * @return string
     */
    function __url(string $url = '', array $vars = [], bool $suffix = true, bool $domain = false): string
    {
        if (filter_var($url, FILTER_VALIDATE_URL)) return $url;
        return url($url, $vars, $suffix, $domain)->build();
    }
}

if (!function_exists('password')) {

    /**
     * 密码加密算法
     * @param $value
     * @return string
     */
    function password($value): string
    {
        $value = sha1('blog_') . md5($value) . md5('_encrypt') . sha1($value);
        return sha1($value);
    }

}


if (!function_exists('sysConfig')) {

    /**
     * 获取系统配置信息
     * @param $group
     * @param $name
     * @return mixed
     */
    function sysConfig($group, $name = null): mixed
    {
        $where = ['group' => $group];
        $value = empty($name) ? Cache::get("sysConfig_{$group}") : Cache::get("sysConfig_{$group}_{$name}");
        if (empty($value)) {
            if (!empty($name)) {
                $where['name'] = $name;
                $value         = \app\admin\model\SystemConfig::where($where)->value('value');
                Cache::tag('sysConfig')->set("sysConfig_{$group}_{$name}", $value, 3600);
            }else {
                $value = \app\admin\model\SystemConfig::where($where)->column('value', 'name');
                Cache::tag('sysConfig')->set("sysConfig_{$group}", $value, 3600);
            }
        }
        return $value;
    }
}

if (!function_exists('array_format_key')) {

    /**
     * 二位数组重新组合数据
     * @param $array
     * @param $key
     * @return array
     */
    function array_format_key($array, $key): array
    {
        $newArray = [];
        foreach ($array as $vo) {
            $newArray[$vo[$key]] = $vo;
        }
        return $newArray;
    }

}

if (!function_exists('auth')) {

    /**
     * auth权限验证
     * @param $node
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    function auth($node = null): bool
    {
        $authService = new AuthService(session('admin.id'));
        return $authService->checkNode($node);
    }

    /**
     * @param string|null $detail
     * @param string $name
     * @param string $placeholder
     * @return string
     */
    function editor_textarea(?string $detail, string $name = 'desc', string $placeholder = '请输入'): string
    {
        $editor_type = sysConfig('site', 'editor_type');
        return match ($editor_type) {
            'ckeditor' => "<textarea name='{$name}' rows='20' class='layui-textarea editor' placeholder='{$placeholder}'>{$detail}</textarea>",
            'ueditor'  => "<script type='text/plain' id='{$name}' name='{$name}' class='editor' data-content='{$detail}'></script>",
            'EasyMDE'  => "<textarea id='{$name}' class='editor' name='{$name}'>{$detail}</textarea>",
            default    => "<div class='wangEditor_div'><textarea name='{$name}' rows='20' class='layui-textarea editor layui-hide'>{$detail}</textarea><div id='editor_toolbar_{$name}'></div><div id='editor_{$name}' style='height: 300px'></div></div>",
        };
    }
}



// 定义公共返回方法
if (!function_exists('output_error')) {
    function output_error($msg = "失败", $code = 0, $status = 'fail')
    {
        output_data(array(), $msg, $code, $status);
    }
}


if (!function_exists('output_success')) {
    function output_success($msg = "成功", $data = array())
    {
        output_data($data, $msg);
    }
}

if (!function_exists('output_data')) {
    function output_data($data = array(), $msg = "成功", $code = 1, $status = 'ok')
    {
        $jsonData = array();
        $jsonData['data'] = $data;
        $jsonData['msg'] = $msg;
        $jsonData['code'] = $code;
        $jsonData['status'] = $status;
        throw new HttpResponseException(json($jsonData, 200));
    }
}

if (!function_exists('result_error')) {
    function result_error($msg = "错误", $success = false, $status = 'fail')
    {
        $result = array(
            'success' => $success,
            'msg' => $msg,
            'data' => array(),
            'status' => $status,
        );

        return $result;
    }
}

if (!function_exists('result_success')) {
    function result_success($msg = "成功", $data = array(), $success = true)
    {
        $result = array(
            'success' => $success,
            'msg' => $msg,
            'data' => $data,
        );

        return $result;
    }
}

if (!function_exists('result_data')) {
    function result_data($data = array(), $msg = "成功", $code = 1)
    {
        $jsonData = array();
        $jsonData['data'] = $data;
        $jsonData['msg'] = $msg;
        $jsonData['code'] = $code;
       return json($jsonData, 200);
    }
}

//curl
if (!function_exists('curl_post')) {
    function curl_post($url = '', $Data = array(), $header = '',$ContentType='')
    {
        if (is_array($Data)) {
            $postData =json_encode($Data);
        }
        if($ContentType == 'json') {
            $ContentType = 'application/json';
        }elseif($ContentType == 'form-data'){
            $ContentType = 'multipart/form-data';
            $postData =$Data;
        }else{
            $ContentType = 'application/x-www-form-urlencoded';
        }

        $header_arr=array(
            'Content-Type:'.$ContentType,
            'Accept:application/json',
            'User-Agent:'.$_SERVER['HTTP_USER_AGENT']
        );
        if($header){
            array_push($header_arr,$header);
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header_arr);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数

        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);

        return $data;
    }

}

if (!function_exists('curl_get')) {
    function curl_get($url,$data, $headers = []) {

        if($data){
            $query = http_build_query($data);
            $url = $url . '?' . $query;
        }

        $ch = curl_init();
        
        // 设置cURL选项
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        
        // 如果提供了自定义头部
        if (!empty($headers)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }
        
        // 对于HTTPS请求
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        
        // 执行请求
        $response = curl_exec($ch);
        curl_close($ch);

        return $response;
    }
}

// 获取系统订单号
if (!function_exists('get_order_num')) {
    function get_order_num($app_type)
    {
        $type_str=[1=>'LKL',2=>'LS',10=>'LKL',20=>'LS'];
        $result = $type_str[$app_type].date('YmdHis').mt_rand(100000, 999999);

        return $result;
    }
}

// 根据app_type获取对应整型
if (!function_exists('get_app_type_int')) {
    function get_app_type_int($app_type)
    {
        $type_str=['lakala_dev'=>1,'leshua_dev'=>2,'lakala_pro'=>10,'leshua_pro'=>20];
        $result = $type_str[$app_type]??'';

        return $result;
    }
}

// 根据app_type获取对应字符串
if (!function_exists('get_app_type_str')) {
    function get_app_type_str($app_type)
    {
        $type_str=[1=>'lakala_dev',2=>'leshua_dev',10=>'lakala_pro',20=>'leshua_pro'];
        $result = $type_str[$app_type]??'';

        return $result;
    }
}

// 根据app_type获取对应中文
if (!function_exists('get_app_type_zw')) {
    function get_app_type_zw($app_type)
    {
        $type_str=['lakala_dev'=>'拉卡拉测试','leshua_dev'=>'乐刷测试','lakala_pro'=>'拉卡拉正式','leshua_pro'=>'乐刷正式'];
        $result = $type_str[$app_type]??'';

        return $result;
    }
}

// 根据app_type获取正式还是测试整型
if (!function_exists('get_pro_dev_int')) {
    function get_pro_dev_int($app_type)
    {
        $type_str=['lakala_dev'=>1,'leshua_dev'=>1,'lakala_pro'=>2,'leshua_pro'=>2];
        $result = $type_str[$app_type]??'';

        return $result;
    }
}

// 根据app_type获取正式还是测试数组
if (!function_exists('get_pro_dev_arr')) {
    function get_pro_dev_arr($app_type)
    {
        $type_str=[1=>['lakala_dev','leshua_dev'],2=>['lakala_pro','leshua_pro']];
        $result = $type_str[$app_type]??'';

        return $result;
    }
}

// 接口字段统一返回格式
if (!function_exists('get_return_data')) {
    function get_return_data($result, $need_field)
    {
        if($result["success"]){
            $result_data=$result["data"];

            if (isset($result_data[0])) {//二维数组
                $result_arr=$result_data[0];
                $need_field=$need_field[0];
            } else {//一维数组
                $result_arr=$result_data;
                $need_field=$need_field;
            }

            $result_key_arr=array_keys($result_arr);

            foreach($need_field as $v){
                if(!in_array($v, $result_key_arr)){
                    return result_error('必要字段未返回');
                }
            }

            return $result;
        }else{
          return $result;
        }
    }
}



/**
 * 高德坐标系(GCJ-02)转百度坐标系(BD-09)
 * @param float $lng 高德经度
 * @param float $lat 高德纬度
 * @return array 百度坐标系数组 ['lng' => 经度, 'lat' => 纬度]
 */
if (!function_exists('gaode_to_baidu')) {
    function gaode_to_baidu($lng, $lat) {
        if(!$lng||!$lat){
          return ['lng' => '', 'lat' => ''];
        }
        $x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        $x = $lng;
        $y = $lat;
        $z = sqrt($x * $x + $y * $y) + 0.00002 * sin($y * $x_pi);
        $theta = atan2($y, $x) + 0.000003 * cos($x * $x_pi);
        $bd_lng = $z * cos($theta) + 0.0065;
        $bd_lat = $z * sin($theta) + 0.006;
        
        return ['lng' => $bd_lng, 'lat' => $bd_lat];
    }
}


 /**
 * 百度坐标系 (BD-09) 转高德坐标系 (GCJ-02)
 * @param float $bd_lon 百度经度
 * @param float $bd_lat 百度纬度
 * @return array 包含高德经纬度的数组 [经度, 纬度]
 */
if (!function_exists('baidu_to_gaode')) {
    function baidu_to_gaode($bd_lon, $bd_lat) {
        if(!$bd_lon||!$bd_lat){
          return ['lng' => '', 'lat' => ''];
        }
        $x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        $x = $bd_lon - 0.0065;
        $y = $bd_lat - 0.006;
        $z = sqrt($x * $x + $y * $y) - 0.00002 * sin($y * $x_pi);
        $theta = atan2($y, $x) - 0.000003 * cos($x * $x_pi);
        $gcj_lon = $z * cos($theta);
        $gcj_lat = $z * sin($theta);
        
        return  ['lng' => $gcj_lon, 'lat' => $gcj_lat];
    }
}

/**
 * 数组索引驼峰转蛇形
 * @param array $array 传入数组
 * @param boolean $isMultiLevel 是否支持递归处理多维数组
 * @return array 输出数组
 */
if (!function_exists('camelToSnake')) {
    function camelToSnake($array, $isMultiLevel = false)
    {
        $result = [];
        foreach ($array as $key => $value) {
            // 将驼峰转为蛇形
            $newKey = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $key));

            // 递归处理多维数组
            if (is_array($value) && $isMultiLevel) {
                $value = camelToSnake($value);
            }

            $result[$newKey] = $value;
        }
        return $result;
        }
}


/**
 * 数组索引蛇转驼峰
 * @param array $array 传入数组
 * @param boolean $isMultiLevel 是否支持递归处理多维数组
 * @return array 输出数组
 */
if (!function_exists('snakeToCamel')) {
    function snakeToCamel($array, $isMultiLevel = false) {
        $result = [];
        foreach ($array as $key => $value) {
            // 将蛇形转为驼峰
            $newKey = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $key))));

            // 递归处理多维数组
            if (is_array($value) && $isMultiLevel) {
                $value = snakeToCamel($value);
            }

            $result[$newKey] = $value;
        }
        return $result;
        }
}

/**
 * 安全元转分（处理字符串输入）
 * @param mixed $yuan 金额（元）
 * @return int 金额（分）
 */
if (!function_exists('yuan_to_fen')) {
    function yuan_to_fen($yuan): int {
        if (!is_numeric($yuan)) {
            throw new InvalidArgumentException('金额必须是数字');
        }
        return (int)round((float)$yuan * 100);
    }
}

/**
 * 安全分转元（处理字符串输入）
 * @param mixed $fen 金额（分）
 * @return int 金额（元）
 */
if (!function_exists('fen_to_yuan')) {
    function fen_to_yuan($fen): string {
        if (!is_numeric($fen)) {
            throw new InvalidArgumentException('金额必须是数字');
        }
        return bcdiv((string)$fen, '100', 2);
    }
}


/**
 * 拉卡拉-公钥解密
 * @param $data
 * @return string
 */
if (!function_exists('publicKeyDecrypt')) {
    function publicKeyDecrypt($data,$pubKey){

        $pubKey = "-----BEGIN PUBLIC KEY-----\n" .
            wordwrap($pubKey, 64, "\n", true)
            . "\n-----END PUBLIC KEY-----";

        $crypto = '';
        foreach (str_split(base64_decode($data), 128) as $chunk) {
            openssl_public_decrypt($chunk, $decryptData, $pubKey);
            $crypto .= $decryptData;
        }
        return $crypto;
    }
}